home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / as / dist / expr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-11  |  29.5 KB  |  987 lines

  1. /* expr.c -operands, expressions-
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * This is really a branch office of as-read.c. I split it out to clearly
  22.  * distinguish the world of expressions from the world of statements.
  23.  * (It also gives smaller files to re-compile.)
  24.  * Here, "operand"s are of expressions, not instructions.
  25.  */
  26.  
  27. #include <ctype.h>
  28. #include "as.h"
  29. #include "flonum.h"
  30. #include "read.h"
  31. #include "struc-symbol.h"
  32. #include "expr.h"
  33. #include "obstack.h"
  34. #include "symbols.h"
  35.  
  36. static void clean_up_expression();    /* Internal. */
  37. extern char EXP_CHARS[];    /* JF hide MD floating pt stuff all the same place */
  38. extern char FLT_CHARS[];
  39.  
  40. #ifdef SUN_ASM_SYNTAX
  41. extern int local_label_defined[];
  42. #endif
  43.  
  44. /*
  45.  * Build any floating-point literal here.
  46.  * Also build any bignum literal here.
  47.  */
  48.  
  49. LITTLENUM_TYPE    generic_buffer [6];    /* JF this is a hack */
  50. /* Seems atof_machine can backscan through generic_bignum and hit whatever
  51.    happens to be loaded before it in memory.  And its way too complicated
  52.    for me to fix right.  Thus a hack
  53.  */
  54. LITTLENUM_TYPE    generic_bignum [SIZE_OF_LARGE_NUMBER];
  55. FLONUM_TYPE    generic_floating_point_number =
  56. {
  57.   & generic_bignum [0],        /* low */
  58.   & generic_bignum [SIZE_OF_LARGE_NUMBER - 1], /* high */
  59.   0,                /* leader */
  60.   0,                /* exponent */
  61.   0                /* sign */
  62. };
  63. /* If nonzero, we've been asked to assemble nan, +inf or -inf */
  64. int generic_floating_point_magic;
  65.  
  66. /*
  67.  * Summary of operand().
  68.  *
  69.  * in:    Input_line_pointer points to 1st char of operand, which may
  70.  *    be a space.
  71.  *
  72.  * out:    A expressionS. X_seg determines how to understand the rest of the
  73.  *    expressionS.
  74.  *    The operand may have been empty: in this case X_seg == SEG_NONE.
  75.  *    Input_line_pointer -> (next non-blank) char after operand.
  76.  *
  77.  */
  78.  
  79. static segT
  80. operand (expressionP)
  81.      register expressionS *    expressionP;
  82. {
  83.   register char        c;
  84.   register char *name;    /* points to name of symbol */
  85.   register struct symbol *    symbolP; /* Points to symbol */
  86.  
  87.   extern  char hex_value[];    /* In hex_value.c */
  88.   char    *local_label_name();
  89.  
  90.   SKIP_WHITESPACE();        /* Leading whitespace is part of operand. */
  91.   c = * input_line_pointer ++;    /* Input_line_pointer -> past char in c. */
  92.   if (isdigit(c))
  93.     {
  94.       register valueT    number;    /* offset or (absolute) value */
  95.       register short int digit;    /* value of next digit in current radix */
  96.                 /* invented for humans only, hope */
  97.                 /* optimising compiler flushes it! */
  98.       register short int radix;    /* 8, 10 or 16 */
  99.                 /* 0 means we saw start of a floating- */
  100.                 /* point constant. */
  101.       register short int maxdig;/* Highest permitted digit value. */
  102.       register int    too_many_digits; /* If we see >= this number of */
  103.                 /* digits, assume it is a bignum. */
  104.       register char *    digit_2; /* -> 2nd digit of number. */
  105.                int    small;    /* TRUE if fits in 32 bits. */
  106.  
  107.       if (c=='0')
  108.     {            /* non-decimal radix */
  109.       if ((c = * input_line_pointer ++)=='x' || c=='X')
  110.         {
  111.           c = * input_line_pointer ++; /* read past "0x" or "0X" */
  112.           maxdig = radix = 16;
  113.           too_many_digits = 9;
  114.         }
  115.       else
  116.         {
  117.           /* If it says '0f' and the line ends or it DOESN'T look like
  118.              a floating point #, its a local label ref.  DTRT */
  119.           if(c=='f' && (! *input_line_pointer ||
  120.                 (!index("+-.0123456789",*input_line_pointer) &&
  121.                  !index(EXP_CHARS,*input_line_pointer))))
  122.         {
  123.               maxdig = radix = 10;
  124.           too_many_digits = 11;
  125.           c='0';
  126.           input_line_pointer-=2;
  127.         }
  128.           else if (c && index (FLT_CHARS,c))
  129.         {
  130.           radix = 0;    /* Start of floating-point constant. */
  131.                 /* input_line_pointer -> 1st char of number. */
  132.           expressionP -> X_add_number =  - (isupper(c) ? tolower(c) : c);
  133.         }
  134.           else
  135.         {        /* By elimination, assume octal radix. */
  136.           radix = 8;
  137.           maxdig = 10;    /* Un*x sux. Compatibility. */
  138.           too_many_digits = 11;
  139.         }
  140.         }
  141.       /* c == char after "0" or "0x" or "0X" or "0e" etc.*/
  142.     }
  143.       else
  144.     {
  145.       maxdig = radix = 10;
  146.       too_many_digits = 11;
  147.     }
  148.       if (radix)
  149.     {            /* Fixed-point integer constant. */
  150.                 /* May be bignum, or may fit in 32 bits. */
  151. /*
  152.  * Most numbers fit into 32 bits, and we want this case to be fast.
  153.  * So we pretend it will fit into 32 bits. If, after making up a 32
  154.  * bit number, we realise that we have scanned more digits than
  155.  * comfortably fit into 32 bits, we re-scan the digits coding
  156.  * them into a bignum. For decimal and octal numbers we are conservative: some
  157.  * numbers may be assumed bignums when in fact they do fit into 32 bits.
  158.  * Numbers of any radix can have excess leading zeros: we strive
  159.  * to recognise this and cast them back into 32 bits.
  160.  * We must check that the bignum really is more than 32
  161.  * bits, and change it back to a 32-bit number if it fits.
  162.  * The number we are looking for is expected to be positive, but
  163.  * if it fits into 32 bits as an unsigned number, we let it be a 32-bit
  164.  * number. The cavalier approach is for speed in ordinary cases.
  165.  */
  166.       digit_2 = input_line_pointer;
  167.       for (number=0;  (digit=hex_value[c])<maxdig;  c = * input_line_pointer ++)
  168.         {
  169.           number = number * radix + digit;
  170.         }
  171.       /* C contains character after number. */
  172.       /* Input_line_pointer -> char after C. */
  173.       small = input_line_pointer - digit_2 < too_many_digits;
  174.       if ( ! small)
  175.         {
  176.           /*
  177.            * We saw a lot of digits. Manufacture a bignum the hard way.
  178.            */
  179.           LITTLENUM_TYPE *    leader;    /* -> high order littlenum of the bignum. */
  180.           LITTLENUM_TYPE *    pointer; /* -> littlenum we are frobbing now. */
  181.           long int        carry;
  182.  
  183.           leader = generic_bignum;
  184.           generic_bignum [0] = 0;
  185.                 /* We could just use digit_2, but lets be mnemonic. */
  186.           input_line_pointer = -- digit_2; /* -> 1st digit. */
  187.           c = *input_line_pointer ++;
  188.           for (;   (carry = hex_value [c]) < maxdig;   c = * input_line_pointer ++)
  189.         {
  190.           for (pointer = generic_bignum;
  191.                pointer <= leader;
  192.                pointer ++)
  193.             {
  194.               long int    work;
  195.  
  196.               work = carry + radix * * pointer;
  197.               * pointer = work & LITTLENUM_MASK;
  198.               carry = work >> LITTLENUM_NUMBER_OF_BITS;
  199.             }
  200.           if (carry)
  201.             {
  202.               if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
  203.             {    /* Room to grow a longer bignum. */
  204.               * ++ leader = carry;
  205.             }
  206.             }
  207.         }
  208.           /* Again, C is char after number, */
  209.           /* input_line_pointer -> after C. */
  210.           know( BITS_PER_INT == 32 );
  211.           know( LITTLENUM_NUMBER_OF_BITS == 16 );
  212.           /* Hence the constant "2" in the next line. */
  213.           if (leader < generic_bignum + 2)
  214.         {        /* Will fit into 32 bits. */
  215.           number =
  216.             ( (generic_bignum [1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS )
  217.             | (generic_bignum [0] & LITTLENUM_MASK);
  218.           small = TRUE;
  219.         }
  220.           else
  221.         {
  222.           number = leader - generic_bignum + 1;    /* Number of littlenums in the bignum. */
  223.         }
  224.         }
  225.       if (small)
  226.         {
  227.           /*
  228.            * Here with number, in correct radix. c is the next char.
  229.            * Note that unlike Un*x, we allow "011f" "0x9f" to
  230.            * both mean the same as the (conventional) "9f". This is simply easier
  231.            * than checking for strict canonical form. Syntax sux!
  232.            */
  233.           if (number<10)
  234.         {
  235. #ifdef SUN_ASM_SYNTAX
  236.           if (c=='b' || (c=='$' && local_label_defined[number])
  237. #else
  238.           if (c=='b')
  239. #endif
  240.             {
  241.               /*
  242.                * Backward ref to local label.
  243.                * Because it is backward, expect it to be DEFINED.
  244.                */
  245.               /*
  246.                * Construct a local label.
  247.                */
  248.               name = local_label_name ((int)number, 0);
  249.               if ( (symbolP = symbol_table_lookup(name)) /* seen before */
  250.               && (symbolP -> sy_type & N_TYPE) != N_UNDF /* symbol is defined: OK */
  251.               )
  252.             {        /* Expected path: symbol defined. */
  253.               /* Local labels are never absolute. Don't waste time checking absoluteness. */
  254.               know(   (symbolP -> sy_type & N_TYPE) == N_DATA
  255.                    || (symbolP -> sy_type & N_TYPE) == N_TEXT );
  256.               expressionP -> X_add_symbol = symbolP;
  257.               expressionP -> X_add_number = 0;
  258.               expressionP -> X_seg          = N_TYPE_seg [symbolP -> sy_type];
  259.             }
  260.               else
  261.             {        /* Either not seen or not defined. */
  262.               as_warn( "Backw. ref to unknown label \"%d:\", 0 assumed.",
  263.                   number
  264.                   );
  265.               expressionP -> X_add_number = 0;
  266.               expressionP -> X_seg        = SEG_ABSOLUTE;
  267.             }
  268.             }
  269.           else
  270.             {
  271. #ifdef SUN_ASM_SYNTAX
  272.               if (c=='f' || (c=='$' && !local_label_defined[number]))
  273. #else
  274.               if (c=='f')
  275. #endif
  276.             {
  277.               /*
  278.                * Forward reference. Expect symbol to be undefined or
  279.                * unknown. Undefined: seen it before. Unknown: never seen
  280.                * it in this pass.
  281.                * Construct a local label name, then an undefined symbol.
  282.                * Don't create a XSEG frag for it: caller may do that.
  283.                * Just return it as never seen before.
  284.                */
  285.               name = local_label_name ((int)number, 1);
  286.               if ( symbolP = symbol_table_lookup( name ))
  287.                 {
  288.                   /* We have no need to check symbol properties. */
  289.                   know(   (symbolP -> sy_type & N_TYPE) == N_UNDF
  290.                    || (symbolP -> sy_type & N_TYPE) == N_DATA
  291.                    || (symbolP -> sy_type & N_TYPE) == N_TEXT);
  292.                 }
  293.               else
  294.                 {
  295.                   symbolP = symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
  296.                   symbol_table_insert (symbolP);
  297.                 }
  298.               expressionP -> X_add_symbol      = symbolP;
  299.               expressionP -> X_seg             = SEG_UNKNOWN;
  300.               expressionP -> X_subtract_symbol = NULL;
  301.               expressionP -> X_add_number      = 0;
  302.             }
  303.               else
  304.             {        /* Really a number, not a local label. */
  305.               expressionP -> X_add_number = number;
  306.               expressionP -> X_seg        = SEG_ABSOLUTE;
  307.               input_line_pointer --; /* Restore following character. */
  308.             }        /* if (c=='f') */
  309.             }            /* if (c=='b') */
  310.         }
  311.           else
  312.         {            /* Really a number. */
  313.           expressionP -> X_add_number = number;
  314.           expressionP -> X_seg        = SEG_ABSOLUTE;
  315.           input_line_pointer --; /* Restore following character. */
  316.         }            /* if (number<10) */
  317.         }
  318.       else
  319.         {
  320.           expressionP -> X_add_number = number;
  321.           expressionP -> X_seg = SEG_BIG;
  322.           input_line_pointer --; /* -> char following number. */
  323.         }            /* if (small) */
  324.     }            /* (If integer constant) */
  325.       else
  326.     {            /* input_line_pointer -> */
  327.                 /* floating-point constant. */
  328.       int error_code;
  329.  
  330.       error_code = atof_generic
  331.         (& input_line_pointer, ".", EXP_CHARS,
  332.          & generic_floating_point_number);
  333.  
  334.       if (error_code)
  335.         {
  336.           if (error_code == ERROR_EXPONENT_OVERFLOW)
  337.         {
  338.           as_warn( "Bad floating-point constant: exponent overflow, probably assembling junk" );
  339.         }
  340.           else
  341.         {          
  342.           as_warn( "Bad floating-point constant: unknown error code=%d.", error_code);
  343.         }
  344.         }
  345.       expressionP -> X_seg = SEG_BIG;
  346.                 /* input_line_pointer -> just after constant, */
  347.                 /* which may point to whitespace. */
  348.       know( expressionP -> X_add_number < 0 ); /* < 0 means "floating point". */
  349.     }            /* if (not floating-point constant) */
  350.     }
  351.   else if(c=='.' && !is_part_of_name(*input_line_pointer)) {
  352.     extern struct obstack frags;
  353.  
  354.     /*
  355.        JF:  '.' is pseudo symbol with value of current location in current
  356.        segment. . .
  357.      */
  358.     symbolP = symbol_new("L0\001",
  359.              (unsigned char)(seg_N_TYPE[(int)now_seg]),
  360.              0,
  361.              0,
  362.              (valueT)(obstack_next_free(&frags)-frag_now->fr_literal),
  363.              frag_now);
  364.     expressionP->X_add_number=0;
  365.     expressionP->X_add_symbol=symbolP;
  366.     expressionP->X_seg = now_seg;
  367.  
  368.   } else if ( is_name_beginner(c) ) /* here if did not begin with a digit */
  369.     {
  370.       /*
  371.        * Identifier begins here.
  372.        * This is kludged for speed, so code is repeated.
  373.        */
  374.       name =  -- input_line_pointer;
  375.       c = get_symbol_end();
  376.       symbolP = symbol_table_lookup(name);
  377.       if (symbolP)
  378.         {
  379.           /*
  380.            * If we have an absolute symbol, then we know it's value now.
  381.            */
  382.           register segT        seg;
  383.  
  384.           seg = N_TYPE_seg [(int) symbolP -> sy_type & N_TYPE];
  385.           if ((expressionP -> X_seg = seg) == SEG_ABSOLUTE )
  386.         {
  387.           expressionP -> X_add_number = symbolP -> sy_value;
  388.         }
  389.       else
  390.         {
  391.           expressionP -> X_add_number  = 0;
  392.           expressionP -> X_add_symbol  = symbolP;
  393.         }
  394.     }
  395.       else
  396.     {
  397.       expressionP -> X_add_symbol
  398.         = symbolP
  399.         = symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
  400.  
  401.       expressionP -> X_add_number  = 0;
  402.       expressionP -> X_seg         = SEG_UNKNOWN;
  403.       symbol_table_insert (symbolP);
  404.     }
  405.       * input_line_pointer = c;
  406.       expressionP -> X_subtract_symbol = NULL;
  407.     }
  408.   else if (c=='(')/* didn't begin with digit & not a name */
  409.     {
  410.       (void)expression( expressionP );
  411.       /* Expression() will pass trailing whitespace */
  412.       if ( * input_line_pointer ++ != ')' )
  413.     {
  414.       as_warn( "Missing ')' assumed");
  415.       input_line_pointer --;
  416.     }
  417.       /* here with input_line_pointer -> char after "(...)" */
  418.     }
  419.   else if ( c=='~' || c=='-' )
  420.     {        /* unary operator: hope for SEG_ABSOLUTE */
  421.       switch(operand (expressionP)) {
  422.       case SEG_ABSOLUTE:
  423.             /* input_line_pointer -> char after operand */
  424.     if ( c=='-' )
  425.       {
  426.         expressionP -> X_add_number = - expressionP -> X_add_number;
  427. /*
  428.  * Notice: '-' may  overflow: no warning is given. This is compatible
  429.  * with other people's assemblers. Sigh.
  430.  */
  431.       }
  432.     else
  433.       {
  434.         expressionP -> X_add_number = ~ expressionP -> X_add_number;
  435.       }
  436.       break;
  437.  
  438.       case SEG_TEXT:
  439.       case SEG_DATA:
  440.       case SEG_BSS:
  441.       case SEG_PASS1:
  442.       case SEG_UNKNOWN:
  443.     if(c=='-') {        /* JF I hope this hack works */
  444.       expressionP->X_subtract_symbol=expressionP->X_add_symbol;
  445.       expressionP->X_add_symbol=0;
  446.       expressionP->X_seg=SEG_DIFFERENCE;
  447.       break;
  448.     }
  449.       default:        /* unary on non-absolute is unsuported */
  450.     as_warn("Unary operator %c ignored because bad operand follows", c);
  451.     break;
  452.     /* Expression undisturbed from operand(). */
  453.       }
  454.     }
  455.   else if (c=='\'')
  456.     {
  457. /*
  458.  * Warning: to conform to other people's assemblers NO ESCAPEMENT is permitted
  459.  * for a single quote. The next character, parity errors and all, is taken
  460.  * as the value of the operand. VERY KINKY.
  461.  */
  462.       expressionP -> X_add_number = * input_line_pointer ++;
  463.       expressionP -> X_seg        = SEG_ABSOLUTE;
  464.     }
  465.   else
  466.     {
  467.               /* can't imagine any other kind of operand */
  468.       expressionP -> X_seg = SEG_NONE;
  469.       input_line_pointer --;
  470.     }
  471. /*
  472.  * It is more 'efficient' to clean up the expressions when they are created.
  473.  * Doing it here saves lines of code.
  474.  */
  475.   clean_up_expression (expressionP);
  476.   SKIP_WHITESPACE();        /* -> 1st char after operand. */
  477.   know( * input_line_pointer != ' ' );
  478.   return (expressionP -> X_seg);
  479. }                /* operand */
  480.  
  481. /* Internal. Simplify a struct expression for use by expr() */
  482.  
  483. /*
  484.  * In:    address of a expressionS.
  485.  *    The X_seg field of the expressionS may only take certain values.
  486.  *    Now, we permit SEG_PASS1 to make code smaller & faster.
  487.  *    Elsewise we waste time special-case testing. Sigh. Ditto SEG_NONE.
  488.  * Out:    expressionS may have been modified:
  489.  *    'foo-foo' symbol references cancelled to 0,
  490.  *        which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
  491.  *    Unused fields zeroed to help expr().
  492.  */
  493.  
  494. static void
  495. clean_up_expression (expressionP)
  496.      register expressionS * expressionP;
  497. {
  498.   switch (expressionP -> X_seg)
  499.     {
  500.     case SEG_NONE:
  501.     case SEG_PASS1:
  502.       expressionP -> X_add_symbol    = NULL;
  503.       expressionP -> X_subtract_symbol    = NULL;
  504.       expressionP -> X_add_number    = 0;
  505.       break;
  506.  
  507.     case SEG_BIG:
  508.     case SEG_ABSOLUTE:
  509.       expressionP -> X_subtract_symbol    = NULL;
  510.       expressionP -> X_add_symbol    = NULL;
  511.       break;
  512.  
  513.     case SEG_TEXT:
  514.     case SEG_DATA:
  515.     case SEG_BSS:
  516.     case SEG_UNKNOWN:
  517.       expressionP -> X_subtract_symbol    = NULL;
  518.       break;
  519.  
  520.     case SEG_DIFFERENCE:
  521.       /*
  522.        * It does not hurt to 'cancel' NULL==NULL
  523.        * when comparing symbols for 'eq'ness.
  524.        * It is faster to re-cancel them to NULL
  525.        * than to check for this special case.
  526.        */
  527.       if (expressionP -> X_subtract_symbol == expressionP -> X_add_symbol)
  528.     {
  529.       expressionP -> X_subtract_symbol    = NULL;
  530.       expressionP -> X_add_symbol        = NULL;
  531.       expressionP -> X_seg            = SEG_ABSOLUTE;
  532.     }
  533.       break;
  534.  
  535.     default:
  536.       BAD_CASE( expressionP -> X_seg);
  537.       break;
  538.     }
  539. }
  540.  
  541. /*
  542.  *            expr_part ()
  543.  *
  544.  * Internal. Made a function because this code is used in 2 places.
  545.  * Generate error or correct X_?????_symbol of expressionS.
  546.  */
  547.  
  548. /*
  549.  * symbol_1 += symbol_2 ... well ... sort of.
  550.  */
  551.  
  552. static segT
  553. expr_part (symbol_1_PP, symbol_2_P)
  554.      struct symbol **    symbol_1_PP;
  555.      struct symbol *    symbol_2_P;
  556. {
  557.   segT            return_value;
  558.  
  559.   know(    (* symbol_1_PP)                   == NULL
  560.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_TEXT
  561.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_DATA
  562.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_BSS
  563.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF
  564.        );
  565.   know(      symbol_2_P             == NULL
  566.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_TEXT
  567.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_DATA
  568.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_BSS
  569.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_UNDF
  570.        );
  571.   if (* symbol_1_PP)
  572.     {
  573.       if (((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
  574.     {
  575.       if (symbol_2_P)
  576.         {
  577.           return_value = SEG_PASS1;
  578.           * symbol_1_PP = NULL;
  579.         }
  580.       else
  581.         {
  582.           know( ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
  583.           return_value = SEG_UNKNOWN;
  584.         }
  585.     }
  586.       else
  587.     {
  588.       if (symbol_2_P)
  589.         {
  590.           if ((symbol_2_P -> sy_type & N_TYPE) == N_UNDF)
  591.         {
  592.           * symbol_1_PP = NULL;
  593.           return_value = SEG_PASS1;
  594.         }
  595.           else
  596.         {
  597.           /* {seg1} - {seg2} */
  598.           as_warn( "Expression too complex, 2 symbols forgotten: \"%s\" \"%s\"",
  599.               (* symbol_1_PP) -> sy_name, symbol_2_P -> sy_name );
  600.           * symbol_1_PP = NULL;
  601.           return_value = SEG_ABSOLUTE;
  602.         }
  603.         }
  604.       else
  605.         {
  606.           return_value = N_TYPE_seg [(* symbol_1_PP) -> sy_type & N_TYPE];
  607.         }
  608.     }
  609.     }
  610.   else
  611.     {                /* (* symbol_1_PP) == NULL */
  612.       if (symbol_2_P)
  613.     {
  614.       * symbol_1_PP = symbol_2_P;
  615.       return_value = N_TYPE_seg [(symbol_2_P) -> sy_type & N_TYPE];
  616.     }
  617.       else
  618.     {
  619.       * symbol_1_PP = NULL;
  620.       return_value = SEG_ABSOLUTE;
  621.     }
  622.     }
  623.   know(   return_value == SEG_ABSOLUTE            
  624.        || return_value == SEG_TEXT            
  625.        || return_value == SEG_DATA            
  626.        || return_value == SEG_BSS            
  627.        || return_value == SEG_UNKNOWN            
  628.        || return_value == SEG_PASS1            
  629.        );
  630.   know(   (* symbol_1_PP) == NULL                
  631.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == seg_N_TYPE [(int) return_value] );
  632.   return (return_value);
  633. }                /* expr_part() */
  634.  
  635. /* Expression parser. */
  636.  
  637. /*
  638.  * We allow an empty expression, and just assume (absolute,0) silently.
  639.  * Unary operators and parenthetical expressions are treated as operands.
  640.  * As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
  641.  *
  642.  * We used to do a aho/ullman shift-reduce parser, but the logic got so
  643.  * warped that I flushed it and wrote a recursive-descent parser instead.
  644.  * Now things are stable, would anybody like to write a fast parser?
  645.  * Most expressions are either register (which does not even reach here)
  646.  * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
  647.  * So I guess it doesn't really matter how inefficient more complex expressions
  648.  * are parsed.
  649.  *
  650.  * After expr(RANK,resultP) input_line_pointer -> operator of rank <= RANK.
  651.  * Also, we have consumed any leading or trailing spaces (operand does that)
  652.  * and done all intervening operators.
  653.  */
  654.  
  655. typedef enum
  656. {
  657. O_illegal,            /* (0)  what we get for illegal op */
  658.  
  659. O_multiply,            /* (1)  * */
  660. O_divide,            /* (2)  / */
  661. O_modulus,            /* (3)  % */
  662. O_left_shift,            /* (4)  < */
  663. O_right_shift,            /* (5)  > */
  664. O_bit_inclusive_or,        /* (6)  | */
  665. O_bit_or_not,            /* (7)  ! */
  666. O_bit_exclusive_or,        /* (8)  ^ */
  667. O_bit_and,            /* (9)  & */
  668. O_add,                /* (10) + */
  669. O_subtract            /* (11) - */
  670. }
  671. operatorT;
  672.  
  673. #define __ O_illegal
  674.  
  675. static operatorT op_encoding [256] = {    /* maps ASCII -> operators */
  676.  
  677. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  678. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  679.  
  680. __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
  681. __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
  682. __, __, __, __, __, __, __, __,
  683. __, __, __, __, O_left_shift, __, O_right_shift, __,
  684. __, __, __, __, __, __, __, __,
  685. __, __, __, __, __, __, __, __,
  686. __, __, __, __, __, __, __, __,
  687. __, __, __, __, __, __, O_bit_exclusive_or, __,
  688. __, __, __, __, __, __, __, __,
  689. __, __, __, __, __, __, __, __,
  690. __, __, __, __, __, __, __, __,
  691. __, __, __, __, O_bit_inclusive_or, __, __, __,
  692.  
  693. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  694. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  695. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  696. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  697. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  698. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  699. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  700. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
  701. };
  702.  
  703.  
  704. /*
  705.  *    Rank    Examples
  706.  *    0    operand, (expression)
  707.  *    1    + -
  708.  *    2    & ^ ! |
  709.  *    3    * / % < >
  710.  */
  711. typedef char operator_rankT;
  712. static operator_rankT
  713. op_rank [] = { 0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1 };
  714.  
  715. segT                /* Return resultP -> X_seg. */
  716. expr (rank, resultP)
  717.      register operator_rankT    rank; /* Larger # is higher rank. */
  718.      register expressionS *    resultP; /* Deliver result here. */
  719. {
  720.   expressionS        right;
  721.   register operatorT    op_left;
  722.   register char        c_left;    /* 1st operator character. */
  723.   register operatorT    op_right;
  724.   register char        c_right;
  725.  
  726.   know( rank >= 0 );
  727.   (void)operand (resultP);
  728.   know( * input_line_pointer != ' ' ); /* Operand() gobbles spaces. */
  729.   c_left = * input_line_pointer; /* Potential operator character. */
  730.   op_left = op_encoding [c_left];
  731.   while (op_left != O_illegal && op_rank [(int) op_left] > rank)
  732.     {
  733.       input_line_pointer ++;    /* -> after 1st character of operator. */
  734.                 /* Operators "<<" and ">>" have 2 characters. */
  735.       if (* input_line_pointer == c_left && (c_left == '<' || c_left == '>') )
  736.     {
  737.       input_line_pointer ++;
  738.     }            /* -> after operator. */
  739.       if (SEG_NONE == expr (op_rank[(int) op_left], &right))
  740.     {
  741.       as_warn("Missing operand value assumed absolute 0.");
  742.       resultP -> X_add_number    = 0;
  743.       resultP -> X_subtract_symbol    = NULL;
  744.       resultP -> X_add_symbol    = NULL;
  745.       resultP -> X_seg = SEG_ABSOLUTE;
  746.     }
  747.       know( * input_line_pointer != ' ' );
  748.       c_right = * input_line_pointer;
  749.       op_right = op_encoding [c_right];
  750.       if (* input_line_pointer == c_right && (c_right == '<' || c_right == '>') )
  751.     {
  752.       input_line_pointer ++;
  753.     }            /* -> after operator. */
  754.       know(   (int) op_right == 0
  755.        || op_rank [(int) op_right] <= op_rank[(int) op_left] );
  756.       /* input_line_pointer -> after right-hand quantity. */
  757.       /* left-hand quantity in resultP */
  758.       /* right-hand quantity in right. */
  759.       /* operator in op_left. */
  760.       if ( resultP -> X_seg == SEG_PASS1 || right . X_seg == SEG_PASS1 )
  761.     {
  762.       resultP -> X_seg = SEG_PASS1;
  763.     }
  764.       else
  765.     {
  766.       if ( resultP -> X_seg == SEG_BIG )
  767.         {
  768.           as_warn( "Left operand of %c is a %s.  Integer 0 assumed.",
  769.               c_left, resultP -> X_add_number > 0 ? "bignum" : "float");
  770.           resultP -> X_seg = SEG_ABSOLUTE;
  771.           resultP -> X_add_symbol = 0;
  772.           resultP -> X_subtract_symbol = 0;
  773.           resultP -> X_add_number = 0;
  774.         }
  775.       if ( right . X_seg == SEG_BIG )
  776.         {
  777.           as_warn( "Right operand of %c is a %s.  Integer 0 assumed.",
  778.               c_left, right . X_add_number > 0 ? "bignum" : "float");
  779.           right . X_seg = SEG_ABSOLUTE;
  780.           right . X_add_symbol = 0;
  781.           right . X_subtract_symbol = 0;
  782.           right . X_add_number = 0;
  783.         }
  784.       if ( op_left == O_subtract )
  785.         {
  786.           /*
  787.            * Convert - into + by exchanging symbols and negating number.
  788.            * I know -infinity can't be negated in 2's complement:
  789.            * but then it can't be subtracted either. This trick
  790.            * does not cause any further inaccuracy.
  791.            */
  792.  
  793.           register struct symbol *    symbolP;
  794.  
  795.           right . X_add_number      = - right . X_add_number;
  796.           symbolP                   = right . X_add_symbol;
  797.           right . X_add_symbol    = right . X_subtract_symbol;
  798.           right . X_subtract_symbol = symbolP;
  799.           if (symbolP)
  800.         {
  801.           right . X_seg        = SEG_DIFFERENCE;
  802.         }
  803.           op_left = O_add;
  804.         }
  805.  
  806.       if ( op_left == O_add )
  807.         {
  808.           segT    seg1;
  809.           segT    seg2;
  810.           
  811.           know(   resultP -> X_seg == SEG_DATA        
  812.            || resultP -> X_seg == SEG_TEXT        
  813.            || resultP -> X_seg == SEG_BSS        
  814.            || resultP -> X_seg == SEG_UNKNOWN        
  815.            || resultP -> X_seg == SEG_DIFFERENCE    
  816.            || resultP -> X_seg == SEG_ABSOLUTE        
  817.            || resultP -> X_seg == SEG_PASS1        
  818.            );
  819.           know(     right .  X_seg == SEG_DATA        
  820.            ||   right .  X_seg == SEG_TEXT        
  821.            ||   right .  X_seg == SEG_BSS        
  822.            ||   right .  X_seg == SEG_UNKNOWN        
  823.            ||   right .  X_seg == SEG_DIFFERENCE    
  824.            ||   right .  X_seg == SEG_ABSOLUTE        
  825.            ||   right .  X_seg == SEG_PASS1        
  826.            );
  827.           
  828.           clean_up_expression (& right);
  829.           clean_up_expression (resultP);
  830.  
  831.           seg1 = expr_part (& resultP -> X_add_symbol, right . X_add_symbol);
  832.           seg2 = expr_part (& resultP -> X_subtract_symbol, right . X_subtract_symbol);
  833.           if (   seg1 == SEG_PASS1
  834.           || seg2 == SEG_PASS1)
  835.         {
  836.           need_pass_2 = TRUE;
  837.           resultP -> X_seg = SEG_PASS1;
  838.         }
  839.           else
  840.         {
  841.           if (seg2 == SEG_ABSOLUTE)
  842.             {
  843.               resultP -> X_seg = seg1;
  844.             }
  845.           else
  846.             {
  847.               know( seg2 != SEG_ABSOLUTE );
  848.               know( resultP -> X_subtract_symbol );
  849.               if (   seg1 != SEG_UNKNOWN
  850.               && seg1 != SEG_ABSOLUTE
  851.               && seg2 != SEG_UNKNOWN
  852.               && seg1 != seg2)
  853.             {
  854.               know( seg1 == SEG_TEXT || seg1 == SEG_DATA || seg1== SEG_BSS );
  855.               know( seg2 == SEG_TEXT || seg2 == SEG_DATA || seg2== SEG_BSS );
  856.               know( resultP -> X_add_symbol      );
  857.               know( resultP -> X_subtract_symbol );
  858.               as_warn("Expression too complex: forgetting %s - %s",
  859.                   resultP -> X_add_symbol      -> sy_name,
  860.                   resultP -> X_subtract_symbol -> sy_name);
  861.               resultP -> X_seg = SEG_ABSOLUTE;
  862.               /* Clean_up_expression() will do the rest. */
  863.             }
  864.               else
  865.             {
  866.               resultP -> X_seg = SEG_DIFFERENCE;
  867.             }    /* If relocation too complex. */
  868.             }        /* If seg2 == SEG_ABSOLUTE. */
  869.         }        /* If need pass 2. */
  870.           resultP -> X_add_number += right . X_add_number;
  871.           clean_up_expression (resultP);
  872.         }
  873.       else
  874.         {            /* Not +. */
  875.           if ( resultP -> X_seg == SEG_UNKNOWN || right . X_seg == SEG_UNKNOWN )
  876.         {
  877.           resultP -> X_seg = SEG_PASS1;
  878.           need_pass_2 = TRUE;
  879.         }
  880.           else
  881.         {
  882.           resultP -> X_subtract_symbol = NULL;
  883.           resultP -> X_add_symbol = NULL;
  884.           /* Will be SEG_ABSOLUTE. */
  885.           if ( resultP -> X_seg != SEG_ABSOLUTE || right . X_seg != SEG_ABSOLUTE )
  886.             {
  887.               as_warn( "Relocation error. Absolute 0 assumed.");
  888.               resultP -> X_seg        = SEG_ABSOLUTE;
  889.               resultP -> X_add_number = 0;
  890.             }
  891.           else
  892.             {
  893.               switch ( op_left )
  894.             {
  895.             case O_bit_inclusive_or:
  896.               resultP -> X_add_number |= right . X_add_number;
  897.               break;
  898.               
  899.             case O_modulus:
  900.               if (right . X_add_number)
  901.                 {
  902.                   resultP -> X_add_number %= right . X_add_number;
  903.                 }
  904.               else
  905.                 {
  906.                   as_warn( "Division by 0. 0 assumed." );
  907.                   resultP -> X_add_number = 0;
  908.                 }
  909.               break;
  910.               
  911.             case O_bit_and:
  912.               resultP -> X_add_number &= right . X_add_number;
  913.               break;
  914.               
  915.             case O_multiply:
  916.               resultP -> X_add_number *= right . X_add_number;
  917.               break;
  918.               
  919.             case O_divide:
  920.               if (right . X_add_number)
  921.                 {
  922.                   resultP -> X_add_number /= right . X_add_number;
  923.                 }
  924.               else
  925.                 {
  926.                   as_warn( "Division by 0. 0 assumed." );
  927.                   resultP -> X_add_number = 0;
  928.                 }
  929.               break;
  930.               
  931.             case O_left_shift:
  932.               resultP -> X_add_number <<= right . X_add_number;
  933.               break;
  934.               
  935.             case O_right_shift:
  936.               resultP -> X_add_number >>= right . X_add_number;
  937.               break;
  938.               
  939.             case O_bit_exclusive_or:
  940.               resultP -> X_add_number ^= right . X_add_number;
  941.               break;
  942.               
  943.             case O_bit_or_not:
  944.               resultP -> X_add_number |= ~ right . X_add_number;
  945.               break;
  946.               
  947.             default:
  948.               BAD_CASE( op_left );
  949.               break;
  950.             } /* switch(operator) */
  951.             }
  952.         }        /* If we have to force need_pass_2. */
  953.         }            /* If operator was +. */
  954.     }            /* If we didn't set need_pass_2. */
  955.       op_left = op_right;
  956.     }                /* While next operator is >= this rank. */
  957.   return (resultP -> X_seg);
  958. }
  959.  
  960. /*
  961.  *            get_symbol_end()
  962.  *
  963.  * This lives here because it belongs equally in expr.c & read.c.
  964.  * Expr.c is just a branch office read.c anyway, and putting it
  965.  * here lessens the crowd at read.c.
  966.  *
  967.  * Assume input_line_pointer is at start of symbol name.
  968.  * Advance input_line_pointer past symbol name.
  969.  * Turn that character into a '\0', returning its former value.
  970.  * This allows a string compare (RMS wants symbol names to be strings)
  971.  * of the symbol name.
  972.  * There will always be a char following symbol name, because all good
  973.  * lines end in end-of-line.
  974.  */
  975. char
  976. get_symbol_end()
  977. {
  978.   register char c;
  979.  
  980.   while ( is_part_of_name( c = * input_line_pointer ++ ) )
  981.     ;
  982.   * -- input_line_pointer = 0;
  983.   return (c);
  984. }
  985.  
  986. /* end: expr.c */
  987.